package gu.simplemq.json;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import gu.simplemq.SimpleLog;
import gu.simplemq.exceptions.SmqNotBeanException;
import gu.simplemq.utils.SPIUtils;

/**
 * JSON实现对象序列化反序列化的抽象类
 * @author guyadong
 *
 */
public abstract class BaseJsonEncoder {
	static{
		/**
		 * SPI(Service Provider Interface)机制加载所有 {@link FastJsonInitializer}实例并执行初始化
		 */
		for(Iterator<FastJsonInitializer> itor = SPIUtils.serviceLoaderOf(FastJsonInitializer.class).iterator();itor.hasNext();){
			try{
				FastJsonInitializer initializer = itor.next();
				SimpleLog.log("FastJsonInitializer: " + initializer.getClass().getName());
				initializer.init();
			}catch (Exception e) {
				SimpleLog.log(e);
			}
		}
	}
	public BaseJsonEncoder() {
	}
	/**
	 * serializes model to Json
	 * @param obj
	 */
	public abstract String toJsonString(Object obj);
	
	/**
	 * 按字段(field)序列化为Map对象
	 * @param obj
	 * @throws SmqNotBeanException
	 */
	public abstract Map<String,String> toJsonMap(Object obj)throws SmqNotBeanException;

	/**
	 * deserialize json into T
	 * @param json
	 * @param type
	 * @return instance of {@code type } or {@code null} if {@code json} is {@code null}
	 */
	public abstract <T> T fromJson(String json, Type type);
	
	/**
	 * deserialize json field map  into T
	 * @param fieldHash
	 * @param type
	 * @return instance of {@code type } or {@code null} if {@code fieldHash} is {@code null} or empty
	 * @throws SmqNotBeanException
	 */
	public abstract <T> T fromJson(Map<String,String> fieldHash, Type type)throws SmqNotBeanException ;
	
	public <T>T fromJson(String json, Class<T> clazz) {		
		return fromJson(json,(Type)clazz);
	}
	
	public <T> T fromJson(Map<String,String> fieldHash, Class<T> clazz)throws SmqNotBeanException {
		return fromJson(fieldHash,(Type)clazz);
	}
	
	public Map<String,Object> fromJson(Map<String,String> fieldHash,Map<String,Type> types){
		if(null == fieldHash) {
			return null;
		}
		LinkedHashMap<String, Object> fields = new LinkedHashMap<String,Object>();
		for(Entry<String, String> entry:fieldHash.entrySet()){
			String field = entry.getKey();
			fields.put(field, this.fromJson(entry.getValue(), null == types ? null : types.get(field)));
		}
		return fields;
	}
	
	public <T>List<Object> toJsonArray(@SuppressWarnings("unchecked") T...array){
		return null == array ? null : toJsonArray(Arrays.asList(array));
	}
	
	public List<Object> toJsonArray(Collection<?> c){
		if(null == c){
			return null;
		}
		ArrayList<Object> list = new ArrayList<Object>(16);
		for( Object element:c){
			try{
				list.add(this.toJsonMap(element));
			}catch(SmqNotBeanException e){
				list.add(this.toJsonString(element));
			}
		}
		return list;
	}
	
	public static final BaseJsonEncoder getEncoder(){
		return FastjsonEncoder.getInstance(); 
	}
}
